/* A simple synchronous XML-RPC client written in C, as an example of
   an Xmlrpc-c client.  This invokes the sample.add procedure that the
   Xmlrpc-c example server.c server provides.  I.e. it adds to numbers
   together, the hard way.
*/
//#define XMLRPC_WANT_INTERNAL_DECLARATIONS
#include <stdlib.h>
#include <stdio.h>

#include <xmlrpc-c/base.h>
#include <xmlrpc-c/client.h>

//#include "config.h"  /* information about this build environment */

#define NAME "Xmlrpc-c Test Client"
#define VERSION "1.0"

static void 
die_if_fault_occurred (xmlrpc_env * const envP) {
    if (envP->fault_occurred) {
        fprintf(stderr, "XML-RPC Fault: %s (%d)\n",
                envP->fault_string, envP->fault_code);
        exit(1);
    }
}

static void
sync_call (xmlrpc_env * env, const char ** serverUrls, int numofserver, int numoftoss, int semantic, const char * methodName)
{
	long int *request_time;
	request_time = (long int *)malloc(sizeof(long int)*numoftoss);
	struct timeval time1,time2;
	int i;
	int numoftail = 0;
	int numofhead = 0;
	int numoferror = 0;
	xmlrpc_value *resultP;
        for(i=0;i<numoftoss;i++)
	{
		gettimeofday(&time1, NULL);
		/* Make the remote procedure call */
        	resultP = xmlrpc_client_call(env, serverUrls, numofserver, semantic, methodName, "(s)", "toss");
		gettimeofday(&time2, NULL);
		request_time[i] = (time2.tv_sec - time1.tv_sec)*1000000 + (time2.tv_usec - time1.tv_usec);
		if(env->fault_occurred==1) {
			numoferror++;
			env->fault_occurred=0;
		}
		else {
        	die_if_fault_occurred(env);

        	const char * const stringValueP;
        	/* Get toss result and print it out. */
        	xmlrpc_read_string(env, resultP, &stringValueP);
        	//printf("Toss result is %s\n", stringValueP);
		if(strcmp("Head", stringValueP)==0)
			numofhead++;
		if(strcmp("Tail", stringValueP)==0)
			numoftail++;
		//if(strcmp("Error", stringValueP)==0)
                //        numoferror++;
		}
	}
	xmlrpc_DECREF(resultP);
	double avgtime = 0;
	for(i=0;i<numoftoss;i++)
	{
		avgtime = avgtime + request_time[i];
	}
	printf("%d|%d|%d|%d|%d|%f\n", semantic, numofhead, numoftail, numoferror, 1, avgtime/numoftoss/1000);
}



int 
main(int           const argc, 
     const char ** const argv) {

    xmlrpc_env env;
    xmlrpc_value * resultP;
    xmlrpc_int32 sum;

	//int semantic = 2;
	int numofserver = 3;
	int numoftoss = 1000;
        if(argc-1 >= 1)
                numoftoss = atoi(argv[1]);
        if(argc-1 >= 2)
	{
                numofserver = atoi(argv[2]);
		if(numofserver%2 == 0)
		{
			fprintf(stderr, "Must be odd number\n");
			exit(1);
		}
		if(numofserver<3||numofserver>11)
		{
			fprintf(stderr, "between 3 and 11\n");
			exit(1);
		}
			
	}
	char **serverUrls;
	serverUrls = (char**)malloc(sizeof(char*)*numofserver);
	int i;
	for(i=0;i<numofserver;i++)
	{
		serverUrls[i]=(char*)malloc(sizeof(char)*256);
		sprintf(serverUrls[i], "http://localhost:80%d/RPC2", i+10);
	}
	const char * const methodName = "toss";

    /* Initialize our error-handling environment. */
    xmlrpc_env_init(&env);

    /* Start up our XML-RPC client library. */
    xmlrpc_client_init2(&env, XMLRPC_CLIENT_NO_FLAGS, NAME, VERSION, NULL, 0);
    die_if_fault_occurred(&env);

	sync_call(&env, serverUrls, numofserver, numoftoss, 1, methodName);
	sync_call(&env, serverUrls, numofserver, numoftoss, 2, methodName);
	sync_call(&env, serverUrls, numofserver, numoftoss, 3, methodName);
	//xmlrpc_value *resultPs;
	//resultPs = xmlrpc_array_new(&env);
	/* Make the remote procedure call */
	//resultP = xmlrpc_client_call(&env, serverUrls, numofserver, semantic, methodName, "(s)", "toss");
	//die_if_fault_occurred(&env);
    
	//const char * const stringValueP;
	/* Get toss result and print it out. */
	//xmlrpc_read_string(&env, resultP, &stringValueP);
	//printf("Toss result is %s\n", stringValueP);	
	/*int size = xmlrpc_array_size(&env, resultPs);
	xmlrpc_value * firstElementP;
	for(i=0;i<size;i++)
	{
		xmlrpc_array_read_item(&env, resultPs, i, &firstElementP);
		xmlrpc_read_string(&env, firstElementP, &stringValueP);
		die_if_fault_occurred(&env);
		printf("Toss result is %s\n", stringValueP);
	}*/
    /* Dispose of our result value. */
    //xmlrpc_DECREF(resultP);

    /* Clean up our error-handling environment. */
    xmlrpc_env_clean(&env);
    
    /* Shutdown our XML-RPC client library. */
    xmlrpc_client_cleanup();

    return 0;
}

